package com.tct.smartRE.fwk.impl.transform.event;

import java.beans.PropertyDescriptor;
import java.util.Map;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import com.tct.smartRE.fwk.api.IBusinessObject;
import com.tct.smartRE.fwk.api.IQueryCondition;
import com.tct.smartRE.fwk.impl.dao.QueryConditionTemplate;
import com.tct.smartRE.fwk.impl.transform.TransformationConstant;
import com.tct.smartRE.fwk.impl.transform.TransformationConstant.ActionEnum;

public class DefaultTransformationEvent extends TransformationEventTemplate {

	public void onConstruction(Map<String, Object> source,
			Map<String, Object> destination) {
		super.onConstruction(source, destination);
		
		ActionEnum actionEnum = (ActionEnum) source
				.get(TransformationConstant.ACTION);
		if (actionEnum.equals(ActionEnum.EDIT_ACTION)) {
			onEditConstruction(source, destination);
		} else if (actionEnum.equals(ActionEnum.FIND_ACTION)) {
			onFindConstruction(source, destination);
		} else if (actionEnum.equals(ActionEnum.COUNT_ACTION)) {
			onCountConstruction(source, destination);
		} else {
			throw new RuntimeException("Unsupported action");
		}
	}

	private void onEditConstruction(Map<String, Object> source,
			Map<String, Object> destination) {
		String classType = (String) source
				.get(TransformationConstant.CLASS_TYPE);
		try {
			Object actualObject = Class.forName(classType).newInstance();

			BeanWrapper beanWrapper = new BeanWrapperImpl(actualObject);

			PropertyDescriptor[] properties = beanWrapper
					.getPropertyDescriptors();
			for (PropertyDescriptor propertyDescriptor : properties) {
				String propertyName = propertyDescriptor.getName();
				if (!propertyName.equals("class")
						&& source.containsKey(propertyName)) {
					Object propertyValue = source.get(propertyName);
					beanWrapper.setPropertyValue(propertyName, propertyValue);
				}
			}
			
			destination.put(TransformationConstant.OBJECT, actualObject);
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	private void onFindConstruction(Map<String, Object> source,
			Map<String, Object> destination) {
		String classType = (String) source.get(TransformationConstant.CLASS_TYPE);
		try {
			final String simpleClassName = Class.forName(classType).getSimpleName();
			IQueryCondition queryCondition = new QueryConditionTemplate() {
				@Override
				public String getQuery() {
					return "from " + simpleClassName;
				}
			};
			
			destination.put(TransformationConstant.OBJECT, queryCondition);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	private void onCountConstruction(Map<String, Object> source,
			Map<String, Object> destination) {
		String classType = (String) source.get(TransformationConstant.CLASS_TYPE);
		try {
			final String simpleClassName = Class.forName(classType).getSimpleName();
			IQueryCondition queryCondition = new QueryConditionTemplate() {
				@Override
				public String getQuery() {
					return "select count(*) from " + simpleClassName;
				}
			};
			
			destination.put(TransformationConstant.OBJECT, queryCondition);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}

	public void onDestruction(IBusinessObject obj,
			Map<String, Object> destination) {
		super.onDestruction(obj, destination);
		
		BeanWrapper beanWrapper = new BeanWrapperImpl(obj);

		PropertyDescriptor[] properties = beanWrapper.getPropertyDescriptors();
		for (PropertyDescriptor propertyDescriptor : properties) {

			String propertyName = propertyDescriptor.getName();
			if (!propertyName.equals("class")) {
				Object value = beanWrapper.getPropertyValue(propertyName);

				if (value != null) {
					destination.put(propertyName, value);
				}
			}
		}
	}

}
